/* Declarations for low-level IO functions.

   This file is part of khipu.

   khipu is free software: you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */

#ifndef __KP_LLIO__
#define __KP_LLIO__   1

#include "interp.hpp"
#include "initop.hpp"

KP_DECLS_BEGIN

#ifdef KP_PLATFORM_UNIX

  typedef int fhandle_t;

inline bool
fhandle_valid_p (fhandle_t fh)
{
  return (fh >= 0);
}

inline fhandle_t
llio_stdfh (unsigned int idx)
{
  return (idx <= 2 ? (fhandle_t)idx : -1);
}

#elif defined (KP_PLATFORM_WINDOWS)
  typedef void* fhandle_t;

KP_EXPORT bool fhandle_valid_p (fhandle_t fh);

#else
#  error "unsupported platform"
#endif

/* Open a file handle given a path and mode. Store the matching
 * stream flags in *FLAGP if not null. */
KP_EXPORT fhandle_t llio_open (interpreter *interp, const char *path,
  const char *mode, int *flagp = nullptr);

// Read at most NBYTES bytes from the file handle FH into DST.
KP_EXPORT int llio_readb (interpreter *interp, fhandle_t fh,
  char *dst, uint32_t nbytes);

// Write at most NBYTES bytes from SRC into file handle FH.
KP_EXPORT int llio_writeb (interpreter *interp, fhandle_t fh,
  const char *src, uint32_t nbytes);

/* Set the file handle position to OFFSET, according to WHENCE in
 * file handle FH. */
KP_EXPORT bool llio_seek (interpreter *interp, fhandle_t fh,
  int64_t& offset, int whence);

// Truncate file handle FH to SIZE bytes.
KP_EXPORT bool llio_truncate (fhandle_t fh, uint64_t size);

// Close file handle FH.
KP_EXPORT bool llio_close (fhandle_t fh);

struct fhandle_stat
{
  int64_t atime;
  int64_t mtime;
  int64_t ctime;
  uint64_t size;
  uint32_t nlink;
#ifdef KP_PLATFORM_UNIX
  uint64_t dev;
  uint64_t ino;
  uint32_t mode;
  int uid;
  int gid;
  uint64_t rdev;
  uint64_t blksize;
  uint64_t blocks;
#elif defined (KP_PLATFORM_WINDOWS)
  uint32_t attr;
  uint32_t serialno;
  uint64_t index;
#else
#  error "unsupported platform"
#endif
};

// Return information for file handle FH in OUT.
KP_EXPORT bool llio_fhstat (interpreter *interp,
  fhandle_t fh, fhandle_stat& out);

// Return a string that represents the realpath for PATH.
KP_EXPORT object llio_fhpath (interpreter *interp, const char *path);

#ifndef KP_PLATFORM_WINDOWS

// In non-windows platforms, binary and text mode are the same.

inline int
llio_readt (interpreter *interp, fhandle_t fh, char *dst, uint32_t nbytes)
{
  return (llio_readb (interp, fh, dst, nbytes));
}

inline int
llio_writet (interpreter *interp, fhandle_t fh, const char *src, uint32_t nb)
{
  return (llio_writeb (interp, fh, src, nb));
}

#else

KP_EXPORT int llio_readt (interpreter *interp, fhandle_t fh,
  char *dst, uint32_t nbytes);

KP_EXPORT int llio_writet (interpreter *interp, fhandle_t fh,
  const char *src, uint32_t nbytes);

// Return the standard file handle for index IDX.
KP_EXPORT fhandle_t llio_stdfh (unsigned int idx);

#endif

// Init OP for low-level IO.
KP_EXPORT init_op init_llio;

KP_DECLS_END

#endif
